Глава 11

Работа с данными

Необходимо подчеркнуть, что если вам доводилось разрабатывать программы по обработке баз данных, используя язык SQL, то изучение данного материала не составит для вас особой сложности.

Замечание

Все примеры в данной главе основаны на разработанной нами базе данных CRUISE, описанной в разд. "Разработка базы данных" гл. 5. В примерах могут встречаться ссылки на основные файлы в рамках проекта "My-Line Cruises", коды которых представлены в приложении 1.

Как уже отмечалось ранее, ColdFusion позволяет работать с данными через драйверы ODBC, OLE DB, а также использовать собственные драйверы для Oracle, Sybase, Informix, DB2. Для реализации представленных здесь примеров мы предварительно создали источник ODBC с именем Cruise в соответствии с наименованием базы данных.

Напомним, что нами была разработана физическая модель базы данных CRUISE для сайта, знакомящего туристов с возможными круизами и экскурсиями, позволяющего бронировать и распространять билеты на текущие круизы.

Также отметим, что при перемещении физической модели CRUISE непосредственно на сервер БД Sybase SQL Anywhere было предложено изменить название таблицы SCHEDULE в связи с требованиями конкретного сервера БД. Поэтому далее таблица, содержащая расписание, будет именоваться как SCHEDULED В таком случае окончательный список таблиц, с которыми предстоит работать, выглядит так:

В ColdFusion существует тег <CFQUERY>, позволяющий передавать SQL-запросы в базу данных как для выполнения определенных действий, так и для извлечения результирующих данных. Это не единственный тег в ColdFusion, предназначенный для работы с базами данных. Однако тег <CFQUERY> можно определить как основной и требующий отдельного внимания.

Тег <CFQUERY>

Синтаксис:

<CFQUERY NAME = "query_name"

DATASOURCE = "ds_riame" DBTYPE = "type" OBSERVER = "dbms"

DBNAME = "database name" CONNECTSTRING = "connection string"

USERNAME = "username" PASSWORD = "password"

MAXROWS = "number" BLOCKFACTOR = "blocksize"

TIMEOUT = "milliseconds" CACHEDAFTER = "date"

CACHEDWITHIN = "timespan" PROVIDER = "COMProvider"

PROVIDERDSN = "datasource" DEBUG = "Yes | No"> SQL-предложения </CFQUERY>

В табл. 11.1 представлено описание атрибутов тега <CF'QUERY>.

Таблица 11.1. Описание атрибутов тега <CFQUER Y>

Атрибут

Описание

NAME


DATASOURCE

Имя запроса. Обязательный атрибут. Должно начинаться с буквы, может включать буквы, цифры и символ подчеркивания. Пробелы недопустимы

Источник данных, к которому обращен запрос. Обязательный атрибут для всех значений атрибутов DBTYPE кроме

DBTYPE="query" И DBTYPE="dynamic"

DBTYPE

OBSERVER DBNAME CONNECTSTRING

Тип драйвера базы данных. Необязательный атрибут. Возможные значения:

  • dynamic — тип соединения с источником данных ODBC, который не определен в "ColdFusion Administrator". При использовании этого значения следует определить всю информацию о связи ODBC с атрибутом CONNECTSTRING;
  • query— использует существующий запрос как источник данных. В этом случае нет необходимости определять атрибут DATASOURCE, вместо этого следует использовать имя существующего запроса в качестве имени таблицы;
  • ODBC — ODBC-драйвер (по умолчанию);
  • Oracle? 3— позволяет использовать собственный драйвер БД Oracle 7.3. В этом случае на компьютере, где инсталлирован ColdFusion Server, должна быть установлена клиентская часть Oracle 7.3.4.0.0 (или более поздняя версия);
  • OracleSO — дает возможность использовать собственный драйвер БД Oracle 8.O. Соответственно должна быть установлена клиентская часть Oracle 8.0 (или более поздняя версия);
  • Sybasell — позволяет использовать собственный драйвер БД Sybase System 1 1 . Соответственно должна быть установлена клиентская часть Sybase System 11.1.1 (или более поздняя версия); рекомендуется с исправлениями ebf 7729;
  • OLEDB — поставщик OLE DB; • DB2 — использование собственного драйвера БД DB2 5.2;
  • Informix73— использование собственного драйвера БД Informix 7.3

Имя сервера БД. Необязательный атрибут. Применяется для собственных драйверов и SQLOLEDB. При определении OBSERVER игнорируется установка источника данных

Имя БД (только для Sybase System 11 и SQLOLEDB). Необязательный атрибут. При определении DBNAME игнорируется БД по умолчанию, установленная в источнике данных

Строка соединения для отправления к ODBC-серверу. Требуется для DBTYPE -"dynamic", необязательный атрибут для всех других типов. При соединении с источником данных, определенным в "ColdFusion Administrator", можно использовать этот атрибут, чтобы определить дополнительные детали соединения ИЛИ переопределить информацию о соединении. Если вы динамически соединяетесь с источником данных, указанным в атрибуте DATASOURCE, определяя DBTYPE="dynamic", строка соединения должна определить все требуемые параметры соединения ODBC

 

Атрибут

Описание

USERNAME

Имя пользователя. Необязательный атрибут. При определении данного атрибута значение USERNAME, указанное в источнике данных, игнорируется

PASSWORD

Пароль пользователя. Необязательный атрибут. При определении данного атрибута значение PASSWORD, указанное в источнике данных, игнорируется

MAXROWS

Определяет максимальное количество записей для возвращаемого результата. Необязательный атрибут. Может принимать значение —1, что позволяет не ограничивать возвращаемое количество записей

BLOCKFACTOR

Максимальное количество записей для одновременной выборки (fetch) с сервера. Необязательный атрибут. Диапазон от 1 (по умолчанию) до 100. Этот атрибут применяется для собственных драйверов Oracle и ODBC-драйверов. Некоторые драйверы ODBC могут динамически уменьшать размер данного блока

TIMEOUT

Максимальное время ожидания выполнения запроса в миллисекундах. Необязательный атрибут. TIMEOUT поддерживается SQL Server 6.x и более поздними версиями. Минимально и максимально допустимые значения зависят от драйвера

CACHEDAFTER

Значение даты. Необязательный атрибут. Позволяет использовать кэширование данных запроса, если дата запроса оригинала принимает более позднее значение даты, установленной с помощью CACHEDAFTER. Эффективно только если в "ColdFusion Administrator" разрешено кэширование запросов. Чтобы применять кэширование данных, текущий запрос должен использовать то же самое SQL-предложение, источник данных, имя запроса, имя пользователя, пароль и тип драйвера

CACHEDWITHIN

Промежуток, использующий функцию ColdFusion CreateTimeSpan. Необязательный атрибут. Позволяет применять кэширование данных запроса, если дата запроса оригинала 'попадает в промежуток времени, который определяется функцией CreateTimeSpan. Эффективно, только если в "ColdFusion Administrator" разрешено кэширование запросов. Чтобы использовать кэширование данных, текущий запрос должен содержать то же самое SQL-предложение, источник данных, имя запроса, имя пользователя, пароль и тип драйвера

PROVIDER

СОМ-поставщик. Необязательный атрибут. Только для OLE DB

PROVIDERDSN

Имя поставщика данных. Необязательный атрибут. Только для OLEDB

DEBUG

Используется для отладки запроса. Необязательный атрибут. Возможные значения:

• Yes —да;

• No — нет (по умолчанию)

 

Атрибут

Описание

USERNAME

Имя пользователя. Необязательный атрибут. При определении данного атрибута значение USERNAME, указанное в источнике данных, игнорируется

PASSWORD

Пароль пользователя. Необязательный атрибут. При определении данного атрибута значение PASSWORD, указанное в источнике данных, игнорируется

MAXROWS

Определяет максимальное количество записей для возвращаемого результата. Необязательный атрибут. Может принимать значение -1, что позволяет не ограничивать возвращаемое количество записей

BLOCKFACTOR

Максимальное количество записей для одновременной выборки (fetch) с сервера. Необязательный атрибут. Диапазон от 1 (по умолчанию) до 100. Этот атрибут применяется для собственных драйверов Oracle и ODBC-драйверов. Некоторые драйверы ODBC могут динамически уменьшать размер данного блока

TIMEOUT

Максимальное время ожидания выполнения запроса в миллисекундах. Необязательный атрибут. TIMEOUT поддерживается SQL Server 6.x и более поздними версиями. Минимально и максимально допустимые значения зависят от драйвера

CACHE DAFTER

Значение даты. Необязательный атрибут. Позволяет использовать кэширование данных запроса, если дата запроса оригинала принимает более позднее значение даты, установленной с помощью CACHEDAFTER. Эффективно только если в "ColdFusion Administrator" разрешено кэширование запросов. Чтобы применять кэширование данных, текущий запрос должен использовать то же самое SQL-предложение, источник данных, имя запроса, имя пользователя, пароль и тип драйвера

CACHE DWITHIN

Промежуток, использующий функцию ColdFusion CreateTimeSpan. Необязательный атрибут. Позволяет применять кэширование данных запроса, если дата запроса оригинала попадает в промежуток времени, который определяется функцией CreateTimeSpan. Эффективно, только если в "ColdFusion Administrator" разрешено кэширование запросов. Чтобы использовать кэширование данных, текущий запрос должен содержать то же самое SQL-предложение, источник данных, имя запроса, имя пользователя, пароль и тип драйвера

PROVIDER

СОМ-поставщик. Необязательный атрибут. Только для OLE DB

PROVIDERDSN

Имя поставщика данных. Необязательный атрибут. Только для OLEDB

DEBUG

Используется для отладки запроса. Необязательный атрибут. Возможные значения:

• Yes —да;

• No - нет (по умолчанию)

Тег <CFQUERY> возвращает сведения о запросе. В частности конструкция CFQUERY.ExecutionTime возвращает измеряемое в миллисекундах время, которое требуется запросу для его выполнения.

Так же тег <CFQUERY> создает объект запроса, обеспечивающий доступ к вспомогательной информации, посредством следующих переменных:

Прежде чем демонстрировать какие-либо примеры, рассмотрим синтаксис SQL-команды SELECT, позволяющей извлекать данные из одной или нескольких таблиц базы данных.

Команда SELECT

Предложение SELECT задает поля, константы и выражения, которые будут отображены в результатах запроса.

Синтаксис:

SELECT [ALL | DISTINCT]

select_item [AS coluntn_name]

[, select_item [AS column_name] ...]

FROM table_name [, table_name ...]

[WHERE join_condition [AND join_condition ...]

[AND I OR filter_condition [AND | OR filter_condition ...]]]

[GROUP BY group_column [, group_column ...]]

[HAVING filter_condition] [UNION [ALL] SELECTcommand]

[ORDER BY order_item [ASC | DESC]

[, order_item [ASC | DESC] ...]]

Параметры:

Опция ALL по умолчанию отображает в результатах запроса все строки.

Опция DISTINCT исключает из результатов запроса повторяющиеся строки. Ее указание в предложении SELECT допустимо только один раз.

Значение select_item задает элемент, который следует включить в столбец результатов запроса. Выбираемые элементы могут быть следующими:

Каждый элемент select_item генерирует один столбец результатов запроса. Если несколько элементов имеют одинаковые имена, укажите перед именем элемента псевдоним таблицы с точкой, чтобы столбцы не повторялись.

Замечание

Применение пользовательских функций в предложении SELECT обладает очевидными плюсами, но, тем не менее, необходимо иметь в виду, что скорость выполнения операций с помощью конструкции SELECT может быть ограничена скоростью выполнения этих пользовательских функций.

Для выбираемого элемента SELECT, являющегося полем или выражением с участием поля, могут быть использованы следующие функции полей:

Задает заголовок столбца в выводе запроса. Это предложение полезно в случае, когда select_item является выражением или содержит функцию поля, а вы хотите назначить столбцу осмысленное имя. Имя column_name может быть выражением, но не может содержать символы, запрещенные в именах табличных полей.

Задает список таблиц, которые содержат данные, извлекаемые по запросу.

Указывает, что в результат запроса включаются лишь некоторые записи. Предложение WHERE требуется при извлечении данных из нескольких таблиц.

Условие join_condition задает поля, которые связывают таблицы, указанные в предложении FROM. Если в запрос включено более одной таблицы, то для каждой таблицы, кроме первой, необходимо определить условие объединения.

Чтобы связать несколько условий объединения, воспользуйтесь оператором AND. Каждое условие объединения имеет следующий формат:

field_namel comparison field_name2

где field_namel — имя поля одной таблицы ;

field_name2 — имя поля другой таблицы, a comparison представляет один из операторов, представленных в табл. 11.2.

Таблица 11.2. Операторы условия объединения

Оператор

Тип сравнения

=

Равно

==

В точности равно

LIKE

Похоже

< >, ! =

Не равно

>

Больше

> =

Больше или равно

<

Меньше

< =

Меньше или равно

 

Группирует строки в запросе, исходя из значений в одном или нескольких столбцах. В качестве group_column можно задать имя обычного поля таблицы, имя поля, содержащего функцию поля SQL, или числовое выражение, указывающее позицию данного столбца в таблице результатов (самый левый столбец имеет номер 1).

Задает условие фильтра, которому должны удовлетворять группы, чтобы быть включенными в результаты запроса. Предложение HAVING следует использовать вместе с конструкцией GROUP BY. Оно может включать сколько угодно условий фильтра, связанных операторами AND и ок. Также можно использовать оператор NOT, изменяющий значение логического выражения на противоположное.

Условие f ilter_condition не может содержать подзапрос.

Предложение HAVING без предложения GROUP BY действует, как предложение WHERE.

Комбинирует окончательные результаты одного запроса SELECT с окончательными результатами другого запроса SELECT. По умолчанию предложение UNION проверяет скомбинированные результаты и удаляет повторяющиеся строки. Чтобы скомбинировать несколько предложений UNION, используйте скобки.

Если задана опция ALL, предложение UNION не будет удалять из комбинированных результатов повторяющиеся строки.

Предложения UNION подчиняются следующим правилам:

Предложение UNION также можно использовать для моделирования внешнего объединения (outer join).

Когда вы объединяете две таблицы в одном запросе, в вывод включаются только записи с совпадающими значениями в объединяемых полях. Если у некоторой записи родительской таблицы нет соответствующей ей записи в дочерней таблице, эта родительская запись не включается в вывод. Внешнее объединение позволяет включить в вывод все записи родительской таблицы вместе с совпадающими записями из дочерней таблицы.

Сортирует результаты запроса по содержимому одного или нескольких столбцов. Каждый аргумент order_item должен соответствовать некоторому столбцу результатов и может представлять собой один из следующих элементов:

Опция ASC задает возрастающий порядок сортировки результатов запроса, в соответствии с элементом (или элементами) order_item, и используется по умолчанию в предложении ORDER BY.

Опция DESC задает убывающий порядок сортировки результатов запроса.

Если вы не задали порядок результатов запроса с помощью предложения ORDER BY, они останутся неупорядоченными.

Первый запрос

Предположим, нам необходимо организовать предварительный запрос для открытия сеанса по заказу билетов на существующие круизы.

Напомним, в девятом пункте бизнес-правил (см. разд. "Бизнес-правила" гл. 5) мы определили, что при регистрации электронный адрес в то же время является входным именем пользователя (Login ID). В этом случае требуется создать диалоговую форму для ввода электронного адреса и пароля потенциального путешественника для последующей проверки наличия регистрации данного покупателя. Исходя из структуры базы данных CRUISE, непосредственно сам запрос будет выглядеть следующим образом:

<CFQUERY NAME="VerificatioriTra" DATASOURCE="lapplication.dsni">

SELECT key_tra, FirstName_tra, LastName_tra, EMail_tra, 'Gender_tra

FROM Traveler WHERE EMail_tra = '#Form.EMail#'

AND Password_tra = '#Form.Password#' </CFQUERY>

где Form.EMail и Form. Password — переменные формы, предварительно заполненные пользователем.

Следующим этапом мы можем создать переменные сессии, позволяющие в дальнейшем определять пользователя на протяжении всей текущей сессии и не затруднять его повторном заполнением диалоговой формы. Этот код выглядит так:

<CFIF VerificationTra.RecordCount eq 1> <CFSET Session.login = "true">

<CFSET Session.traveler.id = #VerificationTra.key_tra#>

<CFSET Session.traveler.gender =#VerificationTra.Gender_tra#>

<CFSET Session.traveler.name = #VerificationTra.FirstName_traf & " " &

#VerificationTra.LastName_tral>

<CFINCLUDE TEMPLATE = "Welcome.cfm">

<CFELSE>

<!--- Неудачная аутентификация (Authenticate failure) --->

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=BuyTickets.cfm?error=l">

</CFIF>

Смысл представленного кода заключается в определении количества записей, полученных в результате запроса, и т. к. разные покупатели не могут иметь один и тот же электронный адрес, то и количество записей данного запроса может равняться 1 при удачной проверке и 0 при неудачной проверке. В данном коде мы использовали встроенную переменную запроса RecordCount.

Далее продемонстрируем полный код страницы BuyTickefts.cfm, позволяющей решить поставленную перед нами задачу (листинг 11.1).

Листинг 11.1. Код страницы BuyTickets.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm">

<link rel="STYLESHEET" type="text/css" href="main.ess">

<script type="text/javascript" language="JavaScript"

src="main.js"></script>

<style type="text/css"> <! —

|Logln { position:absolute; left:20; top:140; width:200;

height:100; margin:0;z-index:0;} —> </style>

<script language=" JavaScript">

if (ie) {document .write ( '<link rel="stylesheet" type="text/css"

'href="main_ie . ess" title="master"> ' ) ; }

function SendPassword() {

if (ie) var EMail = document. forml.EMail. value;

else var EMail =

document . layers [ 'Login' ] .document. forml.EMail. value/-

if (EMail=="") {

alert ('Enter please E-mail'); } else {

location . href ="Sendpassword . cfm?EMail_tra="+EMail ;

}

</script> </HEAD> <BODY onload="init (1) "

bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"

text="Black" alink="#107098" link="#OC!C47"

vlink="#003366"> <CFINCLUDE TEMPLATE = "BasicBlock. cfm">

<CFIF isDefined( "Session. traveler. id") >

<! --- The traveler is already determined --- >

<CFINCLUDE TEMPLATE = "Welcome. cfm"> <CFELSE>

<CFIF isDefined( "Form. EMail") AND isDef ined( "Form. Password" )>

<! --- Проверка путешественника (Verification traveler) --- >

<CFQUERY NAME="VerificationTra" DATASOURCE="#application.dsn#">

SELECT Key_tra, FirstName_tra, LastName_tra, EMail_tra,

Gender_tra FROM Traveler WHERE EMail_tra = ' #Form.EMaili '

AND Password_tra = '# Form. Pass wordtf ' </CFQUERY>

<CFIF VerificationTra.RecordCount eq 1>

<CFSET Session. login = "true">

<CFSET Session. traveler. id = #Verif icationTra. key_tra#>

<CFSET Session. traveler. gender = #Verif icationTra. Gender_tra#>

<CFSET Session. traveler. name = IVerif icationTra. FirstName_tral & " " & #Verif icationTra. LastName tra#>

<CFINCLUDE TEMPLATE = "Welcome.cfm">

<CFELSE>

<!--- Неудачная аутентификация (Authenticate failure) --->

<META HTTP-EQUIV="Refresh" CONTENT="0;

URL=BuyTickets.cfm?error=l"> </CFIF>

<CFELSE>

<CFIF isDefined("Error")>

<CFSET msgError="#application.msgErrorLogini">

<CFELSE>

<CFSET msgError=""> </CFIF>

<DIV id="LogIn">

<FORM action='BuyTickets.cfm' method='post' name='forml'>

<TABLE border='0' cellspacing='0' cellpadding='0'> <TR>

<TRXTD colspan="2" bgcolor="#22c6d" height=l></TD>

<TD colspan="2" height=l></TD></TR>

<TD class="menleft">

<IMG name="bulll" src="bullet2.gif" width="20"

height="20" border="0"></TD>

<TD width="55" class="menleft">Log In</TD>

<TD bgcolor="#122c6d"></TD> <TD class="menleft">

<a href="SignUp.cfm"

onMouseOver="mouse_over_bull{'bul!2', 'Login');

window.status='Sign Up';

return true" onMouseOut="mouse_out_bull('bul!2', 'Login');

window.status='';

return true">

<IMG name="bul12" src="bullet.gif" width="20" height="20"

border="0"></a></TD> <TD width="82"><a href="SignUp. cfm"

onMouseOver="mouse_over_bull('bul12', 'Login');"

onMouseOut="mouse_out_bull('bul12', 'Login');"

class="menleft">Sign Up</a></TD>

<TRXTD colspan="2" height=l></TD>

<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>

</TR> </TABLE>

<TABLE border='0' cellspacing='2' cellpadding='0'>

<TR><TD colspan="2" align="center" class="txtError">

<CFOUTPUT>#msgError#</CFOUTPUT></td></tr>

<TR><TD width="100" align="right" class="txtForm1"> E-Mail</td>

<td class="note"> <input name='EMail' size=' 16'></td></tr> ;

<TR><TD align="right" class="txtForml"> Password</tdxtd class="note">

<input type=' password' name=' Password'

size=' 16'></TD></TR>

<TR><TD align="right">

<input type=' submit' value='Send'></TD><TD>

<input type=' reset' value= ' Clear '></TD></TR>

<TR><TD colspan="2" align="left" class="txtForml">

Forgot your pas sword? <br> <a href=" javascript : SendPassword ( ) ; "

onMouseOver="window. status='Have it emailed to you'; return true"

onMouseOut="window. status=' ' ; return true"> Have it emailed to you</a></TD></TR> </TABLE> </FORM>

</DIV>

</CFIF> </CFIF> </BODY> </HTML>

Как видно из примера, в результате удачного открытия сеанса мы включаем с помощью тега <CFINCLUDE> страницу Welcome. cfm. В листинге 11.2 продемонстрируем код страницы Welcome. cfm.

Листинг 11.2. Код страницы Welcome.cfm

<CFIF ISession. traveler. gendertt eq "1">

<CFSET Appeal="Ms. "> <CFELSE>

<CFSET Appeal="Mr."> </CFIF>

<CFOUTPUT>

<div id="LogIn">

<p class="smalltxt">Welcome<br>Dear #Appeal#

<a href="UpdateTra.cfm">#Session.traveler.name#</a>

, thank you for your interest in My-Cruises Line.</p>

</div>

</CFOUTPUT>

<!--- The information block on cruises --->

<!---...--->

В нашем примере именно на странице Welcome.cfm подразумевается размещение информации.о текущих круизах. Обращаем ваше внимание на то, что в данном примере встречается ссылка на страницу .UpdateTra.cfm, предназначенную для обновления данных о пользователе текущей сессии. Однако об этом чуть позже.

Отметим лишь, что для удачного открытия сессии необходимо наличие в базе данных сведений о зарегистрированных пользователях. Далее мы продемонстрируем пример добавления данных с помощью ColdFusion.

Добавление данных

Для добавления данных в ColdFusion можно прибегнуть к нескольким способам, например, указать команду внутри уже описанного нами тега <CFQUERY>, применить тэг <CFINSERT> или тэг <CFGRID>, частично используемого в рамках тега <CFFORM>. И если о последнем способе мы поговорим в следующей главе, то первые два варианта рассмотрим прямо сейчас.

Прежде чем привести пример добавления данных, рассмотри синтаксис SQL-команды INSERT.

Команда INSERT

Синтаксис:

INSERT INTO table_name [(fname1 [, fname2, ...])]

VALUES (expressionl [, expression2, ...])

Параметры:

Задает имя таблицы, к которой добавляется новая запись.

Определяет имена полей новой записи, в которые вставляются значения.

Задает значения полей, вставляемые в новую запись. Если имена полей опущены, нужно указывать значения полей в порядке, определяемом структурой таблицы.

Пример команды INSERT

Допустим, нам необходимо организовать регистрацию потенциальных покупателей билетов на существующие круизы.

В этом случае требуется создать диалоговую форму для ввода необходимых данных для последующего их добавления в базу данных CRUISE. Тогда запрос в ColdFusion будет выглядеть следующим образом:

<CFSET Birthday = iDateFormat(#Form.Birthday#, "yyyy-mm-dd")#>

<CFQUERY NAME="AddTraveler" DATASOURCE="#application.dsn#">

INSERT INTO Traveler(EMail_tra, FirstName_tra,

LastName_tra, Middlelnitial_tra, Password_tra, Birthday_tra,

PhoneNum_tra, Gender_tra) VALUES('#Form.EMail#',

'#Form.FirstName#',

'#Form.LastName#', '#Form.MiddleInitial#', '#Form.Password#',

'#Birthday#', '#Form.PhoneNum#', #Form.Gender#) </CFQUERY>

Здесь в предложении VALUES перечислены переменные формы, предварительно заполненные пользователем.

Следует отметить, что мы используем БД Sybase, где формат даты по умолчанию представляется как "yyyy-mm-dd", в свою очередь при вводе данных пользователю предлагается вводить свой день рождения с маской "dd-mm-уууу". Поэтому для приведения формата даты к общему знаменателю используется существующая ДЛЯ ЭТИХ целей функция DateFormat.

Далее будем действовать по аналогии с примером открытия сессии, рассмотренным чуть ранее, где создавали переменные сессии, позволяющие в дальнейшем идентифицировать пользователя на протяжении всей текущей сессии и не затруднять его повторным заполнением диалоговой формы. Этот код выглядит так:

<CFQUERY NAME="TravelerExtKey" DATASOURCE="#application.dsn#">

SELECT key_tra FROM Traveler

WHERE EMail_tra='#Form.EMail#' </CFQUERY>

<CFOUTPUT QUERY="TravelerExtKey">

<CFSET Session.login = "true">

<CFSET Session.traveler.id = #TravelerExtKey.key_tra#>

<CFSET Session.traveler.gender = #Form.Gendert>

<CFSET Session.traveler.name = #Form.FirstNamel & " " &

#Form.LastName#>

</CFOUTPUT>

Как видно из примера, прежде чем определить переменную идентификатора пользователя, нам пришлось создать дополнительный запрос на выборку по полю key_tra, т. к. в базе данных CRUISE все уникальные ключи присваиваются автоматически. И только с помощью обращения к уже добавленной записи мы определяем этот уникальный ключ.

В разд. "Проверка переменных" гл. 9 мы уже рассматривали похожий пример по регистрации пользователей без применения базы данных. Здесь же помимо добавления блоков по работе с базой данных мы также несколько изменили код в соответствии с требованием проекта "My-Line Cruises".

Далее продемонстрируем полный код страницы SignUp.cfm, позволяющей решить поставленную перед нами задачу (листинг 11.3).

Листинг 11.3. Код страницы SignUp.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm">

<link rel="STYLESHEET" type="text/css" href="main.ess">

<script type="text/javascript" language="JavaScript"

src="main. js"></script> <style type="text/css">

<! — #SignUp { position:absolute; left:20; top:140; width:200;

height:100; margin:0;z-index:0;} —> </style>

<script language="JavaScript">

if (ie) {document.write('<link rel="stylesheet" type="text/css"

href="main_ie.ess" title="master">');} </script> </HEAD>

<BODY onload="init(1)"

bgcolor="<CFOUTPUT>#application.BGColorPage#

</CFOUTPUT>" text="Black" alink="#107098" link="#iOC1C47" vlink="#003366">

<CFINCLUDE TEMPLATE = "BasicBlock.cfm"> <CFIF isDefined("Session.traveler.id")>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=BuyTickets.cfm">

<CFELSE>

<CFIF isDefined("Form.EMail")> <CFSET DIsuccessful = 1>

<CFSET msgError = "Warning Error!">

<CFIF Len(Form.EMail) le 5 and Form.EMail does not contain "@">

<CFSET msgError = msgError & "<br>" & #application.msgErrorl#>

<CFSET DIsuccessful =. 0> </CFIF>

<CFIF Len(Form.Password) le 4>

<CFSET msgError = msgError & "<br>" & lapplication.msgError2#>

<CFSET DIsuccessful = 0> </CFIF>

<CFIF IsNumeric(Form.Password)>

<CFSET msgError = msgError & "<br>" & fapplication.msgError3t>

<CFSET DIsuccessful = 0> </CFIF>

<CFIF Form.Password not equal Form.Confirm>

<CFSET msgError = msgError & "<br>" &#application.msgError4#>

<CFSET DIsuccessful = 0> </CFIF>

<CFIF Len(Form.FirstName) le 0>

<CFSET msgError = msgError & "<br>" & lapplication.msgError5#>

<CFSET DIsuccessful = 0> </CFIF>

<CFIF Len(Form.LastName) le 0>

<CFSET msgError = msgError & "<br>" & #application.msgError6t>

<CFSET DIsuccessful = 0> </CFIF>

<CFIF not IsDate(Form.Birthday) and Len(Form.Birthday)gt 0>

<CFSET msgError = msgError & "<br>" & lapplication.msgError7#>

<CFSET DIsuccessful = 0> </CFIF>

<CFIF YesNoFormat(DIsuccessful) equal "No"> <!--- Errors -

<CFSET email = #Form.EMail#>

<CFSET fname = #Form.FirstName#>

<CFSET Iname = #Form.LastName#>

<CFSET middle = #Form.MiddleInitial#>

<CFSET bday = #Form.Birthday#>

<CFSET phonen = ttForm.PhoneNum#> <CFELSE>

<!--- Проверка путешественника (Verification traveler) --->

<CFQUERY NAME="VerificationSU" DATASOURCE="#application.dsnl"> SELECT key_tra FROM Traveler

WHERE EMai1_tra = 'tForm.EMaill' </CFQUERY>

<CFIF VerificationSU.RecordCount eq 1>

<!--- The record with this EMail address already exists! --->

<CFELSE>

<!--- Добавление записи (Add record) --->

<CFSET Birthday = IDateFormat(tForm.Birthday#,

"yyyy-mm-dd")tt>

<CFQUERY NAME="AddTraveler" DATASOURCE="#application.dsn#"> INSERT INTO Traveler(EMail_tra, FirstName_tra,

LastName_tra, Middlelnitial_tra, Password_tra, Birthday_tra,

PhoneNum_tra, Gender_tra) VALUES('#Form.EMail#',

'#Form.FirstName#',

1tForm.LastName#', '#Form.MiddleInitial#', 1#Form.Password!', '#Birthday#', '#Form.PhoneNumi', #Form.Gender#) </CFQUERY>

<!--- Извлечение по ключу (Extraction of a key) --->

<CFQUERY NAME="TravelerExtKey"

DATASOURCE="ttapplication.dsn#"> SELECT key_tra

FROM Traveler WHERE EMail_tra='#Form.EMail#' </CFQUERY>

<CFOUTPUT QUERY="TravelerExtKey"> <CFSET Session.login = "true">

<CFSET Session.traveler.id = #TravelerExtKey.key_tra#>

<CFSET Session.traveler.gender = #Form.Gender#>

<CFSET Session.traveler.name = #Form.FirstName# & " " &

#Form.LastName#> </CFOUTPUT> </CFIF>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=BuyTickets . cfm">

<CFEXIT> </CFIF> <CFELSE>

<CFSET email = ""> <CFSET fname = "">

<CFSET Iname = ""> <CFSET middle = "">

<CFSET bday = ""> <CFSET phonen = "">

<CFSET msgError = ""> </CFIF>

<DIV id="SignUp">

<FORM action='SignUp.cfm' method='post' name=' form1' >

<TABLE border='0' cellspacing='0' cellpadding='0'> <TR>

<TR><TD colspan="2" height=l></TD>

<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>

<TD class="menleft"><a href="BuyTickets.cfm"

onMouseOver="mouse_over_bull('bu112',

'SignUp'); window.status='Sign Up'; return true"

onMouseOut="mouse_out_bull('bul!2', 'SignUp');

window.status=''; return true">

<IMG name="bull2" src="bullet.gif" width="20"

height="20" border="0"></a></TD>

<TD width="55"><a href="BuyTickets . cfm"

onMouseOver="mouse_over_bull('bul12', 'SignUp');"

onMouseOut="mouse_out_bull('bul12', 'SignUp');"

class="menleft">Log In</a></TD>

<TD bgcolor="tl22c6d"></TD> <TD class="menleft">

<IMG name="bulll" src="bullet2.gif" width="20"

height="20" border="0"></TD>

<TD width="82" class="menleft">Sign Up</TD>

<TR><TD colspan="2" bgcolor="#122c6d" height=l>

</TD><TD colspan="2" height=l></TD></TR> </TR>

</TABLE>

<TABLE width="300" border="0" cellspacing="2" cellpadding="0">

<TR><TD colspan="2" align="center" class="txtError">

<CFOUTPUT>#msgError#</CFOUTPUT></TD></TR>

<TR><TD align="right" class="txtForml">

E-Mail (Login)</tdxtd width="215" class="txtForm1">

<input name='EMail' size='16'

value="<CFOUTPUT>#email#</CFOUTPUT>">&nbsp;* </TD></TR> *

<TR><TD align="right" class="txtForml"> Password</td>

<td class="txtForml">

<input type='password' name='Password'

size="16' >&nbsp; *</TD></TR>

<TR><TD align="right" class="txtForml"> Confirm</td>

<td class="txtForml"> <input type='password' name='Confirm'

size='16'>&nbsp;*</TD></TR>

<TR><TD align="right" class="txtForml">

First Name</td><td class="txtForml">

<input name='FirstName' size='16'

value="<CFOUTPUT>#fname#</CFOUTPUT>">&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">

Last Name</td><td class="txtForml"> <input name='LastName' size='16'

value="<CFOUTPUT>#lnamel</CFOUTPUT>">&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForml"> Middle Initial</td>

<td> <input name='MiddleInitial' size='l'

value="<CFOUTPUT>#middle#</CFOUTPUT>"></TD></TR>

<TR><TD align="right" class="txtForml"> Birthday</td>

<td class="txtForml"> <input name=' Birthday' size='10'

value="<CFOUTPUT>#bday#</CFOUTPUT>">&nbsp; dd-mm-yyyy</TD></TR>

<TR><TD align="right" class="txtForml"> Phone Num.</td>

<td> <input name= ' PhoneNum ' size='10'

value="<CFOUTPUT>fphonen#</CFOUTPUT>"></TD></TR>

<TR><TD align="right" class="txtForml"> Gender</TD>

<TD> <select name= ' Gender '>

<option value="0">male <option value="l">female </select></TD></TR>

<TR><TD align=" right ">

<input type= ' submit ' value=' Add '></TD><TD>

<input type=' reset' value= ' Clear '></TD></TR> </TABLE> </FORM>

</CFIF> </BODY> </HTML>

Отметим то, что сообщения об ошибках определены в конфигурационном файле Application.cfm так, как это показано в разд. "Пример файла Application. cf т" гл. 10.

Также для добавления данных в ColdFusion можно использовать тег <CFINSERT>, о чем и пойдет речь в следующем! разделе с предварительным описанием этого тега.

Тег <CFINSERT>

Синтаксис:

<CFINSERT DATASOURCE = "ds_name"

DBTYPE = "type"

DBSERVER = "dbms"

DBNAME = "database name"

TABLENAME = "tbl name"

CONNECTSTRING = "connection string"

TABLEOWNER = "owner"

TABLEQUALIFIER = "tbl_qualifier"

USERNAME = "username"

PASSWORD = "password"

PROVIDER = "COMProvider"

PROVIDERDSN = "datasource"

FORMFIELDS = "formfield1, formfield2, . . . ">

В табл. 11.3 представлено описание атрибутов тега <CFINSERT>.

Таблица 11.3. Описание атрибутов тега <CFINSERT>

Атрибут

Описание

DATASOURCE DBTYPE

Источник данных, к которому обращен запрос. Обязательный атрибут для всех DBTYPE кроме DBTYPE="query" и DBTYPE=" dynamic"

Тип драйвера базы данных. Необязательный атрибут. Возможные значения:

  • dynamic — тип соединения с источником данных ODBC, который не определен в "ColdFusion Administrator". При использовании этого значения следует определить всю информацию о связи ODBC с атрибутом CONNECTSTRING;
  • query— использует существующий запрос как источник данных. В этом случае нет необходимости определять атрибут DATASOURCE, вместо этого следует использовать имя существующего запроса в качестве имени таблицы;
  • ODBC — ODBC-драйвер (по умолчанию);
  • Oracle73— позволяет использовать собственный драйвер БД Oracle 7.3. В этом случае на компьютере, где инсталлирован ColdFusion Server, должна быть установлена клиентская часть Oracle 7.3.4.0.0 (или более поздняя версия);
  • Oracle80 — дает возможность использовать собственный драйвер БД Oracle 8.0. Соответственно должна быть установлена клиентская часть Oracle 8.0 (или более поздняя версия);
  • Sybasell — позволяет использовать собственный драйвер БД Sybase System 11. Соответственно должна быть установлена клиентская часть Sybase System 11.1.1 (или более поздняя версия); рекомендуется с исправлениями ebf 7729;
  • OLEDB — поставщик OLE DB;
  • DB2 — использование собственного драйвера БД DB2 5.2;
  • Informix? 3— использование собственного драйвера БД Informix 7.3

 

Атрибут

Описание

OBSERVER

Имя сервера БД. Необязательный атрибут. Применяется для собственных драйверов и SQL OLEDB. При определении DBSERVER игнорируется установка источника данных

DBNAME

Имя БД (только для Sybase System 11 и SQL OLEDB). Необязательный атрибут. При определении DBNAME игнорируется БД по умолчанию, установленная в источнике данных

TABLENAME

Имя таблицы. Обязательный атрибут. Обратите внимание на следующее:

  • при использовании драйверов Oracle значение этого атрибута должно быть записано в верхнем регистре;
  • при использовании драйвера Sybase значение этого атрибута должно быть в том же самом регистре, в котором была создана данная таблица.

CONNECTSTRING

Строка соединения для отправления к серверу ODBC. Требуется для DBTYPE ="dynamic". Необязательный атрибут для всех других типов. При соединении с источником данных, определенным в "ColdFusion Administrator", можно использовать этот атрибут, чтобы определить дополнительные детали соединения или переопределить информацию соединения. Если вы динамически соединяетесь с источником данных, указанным в атрибуте DATASOURCE, определяя DBTYPE="dynamic", строка соединения должна определить все требуемые параметры соединения ODBC

TABLEOWNER

Владелец таблицы. Необязательный атрибут. Может применяться для источников данных, поддерживающих собственность (ownership) на таблицу (например, SQL Server, Oracle и Sybase SQL Anywhere)

TABLEQUALIFLER

Описатель таблицы. Необязательный атрибут. Может использоваться для источников данных, поддерживающих описатель таблиц (qualifiers). Для SQL Server и Oracle обращается к имени базы данных, которая содержит таблицу. Для dBase-драйверов происходит обращение к каталогу, где размещаются dbf-файлы

USERNAME

Имя пользователя. Необязательный атрибут. При определении данного атрибута значение USERNAME, указанное в источнике данных, игнорируется

PASSWORD

Пароль пользователя. Необязательный атрибут. При определении данного атрибута значение PASSWORD, указанное в источнике данных, игнорируется

PROVIDERDSN Имя поставщика данных. Необязательный атрибут. Только для OLEDB
FORMFIELDS Список полей, разделенных запятыми. Необязательный атрибут. Если этот атрибут не определен, то все поля формы участвуют в операции добавления

PROVIDER

СОМ-поставщик. Необязательный атрибут. Только для OLE DB

 

Пример тега <CFINSERT>

Чтобы демонстрировать использование тега <CFINSERT>, предназначенного для добавления записей в базу данных, рассмотрим пример,, позволяющий регистрировать новые экскурсионные поездки и круизы.

Решим данную задачу по аналогии с предыдущим примером: создадим диалоговую форму, предназначенную для ввода необходимых данных с целью их последующего добавления в базу данных CRUISE, а именно — в таблицу TOUR. Прежде чем представить полный код страницы, продемонстрируем отрывок этого кода, где, собственно говоря, и происходит добавление новых значений:

<!--- Проверка тура (Verification tour) --->

<CFQUERY NAME="VerificationNewTour" DATASOURCE="#application.dsn#">

SELECT key_tou

FROM Tour WHERE Name__tou='IForm.Name_toutt' </CFQUERY>

<CFIF VerificationNewTour.RecordCount eq 1>

<!--- The record with this Name tour already exists! --->

<CFELSE>

<!--- Добавление записи (Add record) --->

<CFINSERT DATASOURCE = "#application.dsn#" TABLENAME = "Tour"

FORMFIELDS = "Name_tou,PointDepart_tou,NumLandingPlaces_tou, Time_tou,CostAdult_tou, CostChildren_tou, CostSenior_tou,

Photo__tou, Note_tou"> </CFIF>

<META HTTP-EQUIV="Refresh" CONTENT="0;

URL=AdminListTour.cfm">

Здесь, прежде чем произвести добавление новой записи, создаем дополнительный запрос, позволяющий проверить, существует ли данный круиз в текущей базе данных. И только при отсутствии круиза совершаем добавление введенных пользователем данных и активизируем страницу со списком всех зарегистрированных круизов.

В листинге 11.4 представлен полный код страницы AdminNewTour.cfm, позволяющей решить сформулированную выше задачу.

Листинг 11.4. Код страницы AdminNewTour.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm">

<link rel="STYLESHEET" type="text/css" href="main.css">

<script type="text/javascript" language="JavaScript"

src="main. js"></script> <style type="text/css">

<! — #Tour { position:absolute; left:20; top:140; width:200;'height:100;

margin:0; z-index:0;} —>

</style> <script language="JavaScript">

if (ie) (document.write{'<link rel="stylesheet" type="text/css"

href="main_ie.ess" title="master">');} </script> </HEAD> <BODY onload="init(1)"

bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>" text="Black" alink="#107098" link="#OC1C47" vlink="#003366"> <CFINCLUDE TEMPLATE = "BasicBlock.cfm"> <CFIF isDefined("Form.Name_tou")> <CFSET DIsuccessful = 1>

<CFSET msgError =-"Warning Error!">

<CFIF Len(Form.Name_tou) le 0 or Len(Fqrm.PointDepart_tou) le 0 or Len(Form.NumLandingPlaces_tou) le 0 or Len(Form.Time_tou) le 0 or Len(Form.CostAdult_tou) le 0 or Len(Form.CostChildren_tou) le 0

or Len(Form.CostSenior_tou) le 0> <CFSET msgError = msgError & "<br>" & "The fields marked with

a symbol *, should not be empty!"> <CFSET DIsuccessful = 0> </CFIF>

<CFIF YesNoFormat(DIsuccessful) equal "No"> <!--- Ошибки (Errors) --->

<CFSET Name_tou = #Form.Name_tou#>

<CFSET PointDepart_tou = #Form.PointDepart_tou#>

<CFSET NumLandingPlaces_tou = #Form.NumLandingPlaces_tou#>

<CFSET Time_tou = #Form.Time_tou#>

<CFSET CostAdult_tou = #Form.CostAdult_tout>

<CFSET CostChildren_tou = iForm.CostChildren_toul>

<CFSET CostSenior_tou = #Form.CostSenior_tou#>

<CFSET Photo_tou = #Form.Photo_tou#>

<CFSET Note tou = #Form.Note tou#>

<CFELSE>

<!---Verification tour--->

<CFQUERY NAME="VerificationNewTour"

DATASOURCE="#application.dsn#"> SELECT key_tou

FROM Tour WHERE Name_tou = '#Form.Name_tou#' </CFQUERY> <CFIF VerificationNewTour.RecordCount eq 1>

<!--- The record with this Name tour already exists! --->

<CFELSE>

<!--- Добавление записи (Add record) --->

<CFINSERT DATASOURCE = "#application.dsn#" TABLENAME = "Tour"

FORMFIELDS = "Name_tou,PointDepart_tou, NumLandingPlaces_tou, Time_tou,CostAdult_tou, CostChildren_tou,CostSenior_tou, Photo_tou,Note_tou"> </CFIF>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=AdminListTour.cfm">

<CFEXIT> </CFIF> <CFELSE>

<CFSET Name_tou = ""> <CFSET PointDepart_tou = "">

<CFSET NumLandingPlaces_tou = ""> <CFSET Time_tou = "">

<CFSET CostAd.ult_tou = ""> <CFSET CostChildren_tou = "">

<CFSET CostSenior_tou = ""> <CFSET Photo_tou = "">

<CFSET Note_tou = ""> <CFSET msgError = ""> </CFIF>

<DIV id="Tour">

<FORM action='AdminNewTour.cfm' method='post' name='forml'>

<TABLE width="370" border="0" cellspacing="0" cellpadding="0"> <TR>

<TR><TD colspan="2" height=l></td>

<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>

<TD class="menleft"><a href="AdminListTour.cfm"

onMouseOver=" mouse_over_bull('bul12', 'Tour');

window.status='List Tour1;

return true" onMouseOut="mouse_out_bull('bul12', 'Tour');

window.status=''; return true">

<img name="bu!12" src="bullet.gif" width="20"

height="20" border="0"></a></td>

<TD width="155"xa href="AdminListTour.cfm"

onMouseOver=" mouse_over_bull('bul12', 'Tour');" onMouseOut=" mouse_out_bull('bul12', 'Tour');"

class="menleft"> List Tour</a></TD>

<TD bgcolor="#122c6d"x/TD> <TD class="menleft">

<img name="bulll" src="bullet2.gif" width="20"

height="20" border="0"></TD>

<td width="215" class="menleft">New Tour</TD>

<TR><TD colspan="2" bgcolor="#122c6d" height=l></TD>

<TD colspan="2" height=l></TD></TR> </TR> </TABLE>

<TABLE width="390" border="0" cellspacing="2" cellpadding="0">

<TR><TD colspan="2" align="center" class="txtError">

<CFOUTPUT>fmsgErrorl</CFOUTPUT></TD></TR>

<TR><TD align="right" class="txtForml">

Name tour</tdxtd width="230" class="txtForml">

<input name='Name_tou' size='30'

value="<CFOUTPUT>iName_tou#</CFOUTPOT>">&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">

Point of departure</tdxtd class="txtForml">

<input name='PointDepart_tou' size='30'

value="<CFOUTPUT>lPointDepart_toul

</CFOUTPUT>">&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForm1">

Number of landing places</tdxtd class="txtForml">

<input name='NumLandingPlaces_tou' size='6'

value="<CFOUTPUT>lNumLandingPlaces_tou

#</CFOUTPUT>">&nbsp;*

</TD></TR>

<TR><TD align="right" class="txtForml">

Time in tour</TD><TD class="txtForml">

<input name='Time_tou' size='2'

value="<CFOUTPUT>#Time_tou#

</CFOUTPUT>">&nbsp; hours, Snbsp; * </TD></TR>

<TR><TD align="right" class="txtForml">

Cost for adults</tdxtd class="txtForml">

<input name='CostAdult_tou' size='6'

value="<CFOUTPUT>#CostAdult_tou#

</CFOUTPUT>">&nbsp; $, Snbsp; * </TD></TR>

<TR><TD align="right" class="txtForml">

Cost for children</td><td class="txtForml">

<input name='CostChildren_tou' size='6'

value="<CFOUTPUT>#CostChildren_tou#

</CFOUTPUT>">&nbsp;$,&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">

Cost for senior citizens</tdxtd class="txtForml">

<input name='CostSenior_tou' size='6'

value="<CFOUTPUT>#CostSenior_tou#

</CFUUTPUT>">&nbsp;$, Snbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">Photo</TD><TD>

<input name= ' Photo_tou ' type="File"

accept="image/gif "

size= ' 23 ' value="<CFOUTPUT>#Photo_4ou#

</CFOUTPUT>"> </TD></TR>

<TR><TD align="right" class="txtForml">Note</TD><TD>

<textarea name = "Note_tou" cols = "33" rows = "4"> . <CFOOTPUT>#Note_tou#</CFOUTPUT></textarea></TD></TR>

<TR><TD align="right">

<input type= ' submit ' value=' Add '></TD><TD>

<input type=' reset' value= ' Clear '></TD>

</TR> </TABLE> </FORM>

</BODY> </HTML>

Обращаем ваше внимание на то, что в данном примере переменные формы именуются в соответствии с названием полей таблицы приемника данных.

Вывод результатов

Теперь, когда мы уже имеем представление о построении запросов и добавлении данных, видимо следует перейти к объяснению, каким образом можно выводить данные, полученные в результате выполнения того или иного запроса.

Итак, для вывода данных в ColdFusion можно прибегнуть к нескольким способам: либо использовать тег <CFOUTPUT>, либо <CFTABLE> в сочетании с тегом <CFCOL>. Впрочем, для этой цели также можно воспользоваться тегом <CFGRID>, используемым в рамках тега <CFFORM>, но об этом поговорим в следующей главе.

Тег <CFOUTPUT>

Синтаксис:

<CFOUTPUT QUERY = "query_name"

GROUP = "query_column"

GROUPCASESENSITIVE = "Yes | No"

STARTROW = "start_row"

MAXROWS = "max_rows_output"> </CFOUTPUT>

В табл. 11.4 представлено описание атрибутов тега <CFOUTPUT>.

Таблица 11.4. Описание атрибутов тега <CFOUTPUT>

Атрибут

Описание

QUERY GROUP


GROUPCASESENSITIVE


STARTROW MAXROWS

Имя запроса. Необязательный атрибут. Для вывода результатов запроса внутри блока <CFOUTPUT>

Имя колонки запроса. Необязательный атрибут. Предполагает группировку результата запроса по указанной колонке (полю таблицы)

Восприимчивость к регистру. Необязательный атрибут. Используется для указания учета регистра при группировке результата запроса. Возможные значения:

• Yes — да (по умолчанию);

• No — нет

Номер записи, с которой следует выводить полученные данные. Необязательный атрибут

Максимальное количество записей, которое следует выводить внутри блока <CFOUTPUT>. Необязательный атрибут

 

Пример тега <CFOUTPUT>

Мы уже неоднократно применяли тег <CFOUTPUT> для вывода значений различных переменных, но при этом ни разу не использовали данную конструкцию в сочетании с описанными выше атрибутами. Здесь же мы постараемся восполнить этот пробел.

Предположим, перед нами стоит задача вывести все круизы, зарегистрированные в базе данных.

Для решения данной задачи предварительно следует построить запрос, например таким образом:

<CFQUERY NAME="GetTour" DATASOURCE="#application.dsn#">

SELECT Key__tou, Name_tou, PointDepart_tou,

NumLandingPlaces__tou, Time_tou, CostAdult_tou,

CostChildren_tou, CostSenior_tou FROM Tour </CFQUERY>

где GetTour — имя запроса.

После чего выведем список полученных данных с указанием имени запроса следующим образом:

<TABLE width="630" border="0" cellspacing="2" cellpadding="0">

<CFOUTPUT QUERY="GetTour">

<TR align="right">

<TD class="txtTab" align="left"> <a href="AdminUpdateTour.cfm?key_tou=#Key_tou#"> #Name_tou#</a></TD>

<TD class="txtTab" align="left">#PointDepart_tou#</TD>

<TD class="txtTab">#NumLandingPlaces_tou#</TD>

<TD class="txtTab">#Time_tou#-hr</TD>

<TD class="txtTab">$#CostAdult_tou#</TD>

<TD class="txtTab">$#CostChildren_tou#</TD>

<TD class="txtTab">$#CostSenior_tou#</TD>

<TD class="txtTab" align="center">

<a href="AdminNoteTour.cfm?key_tou=#Key_tou#" target="_blank">

<FONT face="Wingdings">±</FONT></a></TD> </TR>

</CFOUTPUT> </TABLE>

Допустим, если бы была необходимость вывести 5 записей, начиная с шестой позиции, для этого достаточно было бы добавить еще два атрибута:

<CFOUTPUT QUERY="GetTour" STARTROW="6" MAXROWS="5">

На рис. 11.1 представлен список всех круизов, зарегистрированных в базе данных, в рамках проекта "My-Line Cruises".

Рис. 11.1. Пример вывода списка круизов

Далее продемонстрируем полный код страницы AdminListTour.cfm, позволяющей решить описанную выше задачу (листинг 11.5).

Листинг 11.5. Код страницы AdminListTour.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm">

<link rel="STYLESHEET" type="text/css" href="main.css">

<script type="text/javascript" language="JavaScript"

src="main. js"x/script> <style type="text/css"> <! —

#Tour { position:absolute; left:20; top:140; width:200; height:100;

margin:0; z-index:0;} —>

</style> <script language="JavaScript">

if (ie) {document.write('<link rel="stylesheet" type="text/css"

href="main_ie.ess" title="master">'};} </script> </HEAD>

<BODY onload="init(1)"

bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>" text="Black" alink="#107098" link="#OC1C47" vlink="§003366">

<CFINCLUDE TEMPLATE = "BasicBlock.cfm">

<CFQUERY NAME="GetTour" DATASOURCE="#application.dsn#">

SELECT Key_tou, Name_tou, PointDepart_tou, NumLandingPlaces_tou, Time_tou, CostAdult_tou, CostChildren_tou, CostSenior_tou FROM Tour </CFQUERY>

<DIV id="Tour">

<TABLE width="370" border="0" cellspacing="0" cellpadding="0"> <TR>

<TR><TD colspan="2" bgcolor="#122c6d" height=l></TD>

<TD colspan="2" height=l></TD></TR> <TD class="menleft">

<IMG name="bulll" src="bullet2.gif" width="20" height="20"

border="0"></TD>

<TD width="155" class="menleft">List Tour</TD>

<TD bgcolor="H22c6d"></TD> <TD class="menleft">

<a href="AdminNewTour.cfm"

onMouseOver="mouse_over_bull('bull2', 'Tour');

window.status='New Tour'; return true"

onMouseOut="mouse_out_bull('bull2', 'Tour');

window.status=''; return true">

<IMG name="bull2" src="bullet.gif" width="20" height="20"

border="0"></a></TD> <TD width="215"xa href="AdminNewTour.cfm"

onMouseOver="mouse_over_bull('bul12', 'Tour');"

onMouseOut="mouse_out_bull('bul12', 'Tour');"

class="menleft"> New Tour</ax/td> <TR><TD colspan="2" height=lx/TD>

<TD colspan="4" bgcolor="#122c6d" height=lx/TDx/TR> </TR> </TABLE>

<br>

<TABLE width="630" border="0" cellspacing="2" cellpadding="0">

<TR align="center">

<TD class="txtTitleTab" width="160" align="left">Name tour</TD>

<TD class="txtTitleTab" width="175" align="left">

Point of departure</TD>

<TD class="txtTitleTab" width="40">Places</td>

<TD class="txtTitleTab" width="55">Time</TD>

<TD class="txtTitleTab" width="55">Adults</TD>

<TD class="txtTitleTab" width="55">Children</TD>

<TD class="txtTitleTab" width="55">Seniors</TD>

<TD class="txtTitleTab" width="35">Note</TD> </TR>

<CFOUTPOT QUERY="GetTour"> <TR align="right">

<TD class="txtTab" align="left">

<a href="AdminUpdateTour .cfm?key_tou=#Key_tou#">

#Name_tou#</a></td>

<TD class="txtTab" align="left">#PointDepart_tou#</TD>

<TD class="txtTab">#NumLandingPlaces_tou#</TD>

<TD class="txtTab">fTime_tou#-hr</TD>

<TD class="txtTab">$#CostAdult_tou#</TD>

<TD class="txtTab">$#CostChildren_touf</TD>

<TD class="txtTab">$#CostSenior_toul</TD>

<TD class="txtTab" align="center">

<a href="AdminNoteTour . cfm?key_tou=#Key_tout"

target="_blank">

<FONT face="Wingdings">±</FONTx/a></TD> </TR>

</CFOUTPUT> </TABLE>

</div>

</BODY> </HTML>

Обращаем ваше внимание на то, что в данном примере встречаются две ссылки: на страницу AdminUpdateTour.cfm, предназначенную для обновления выбранной записи, и страницу AdminNoteTour.cfm, служащую для вывода дополнительной информации по текущей записи. Что касается обновления данных, то об этом чуть позже.

Сейчас же рассмотрим страницу AdminNoteTour.cfm, куда, как видно из кода страницы AdmlnListTour.cfm, передается значение поля Key_tou текущей записи. Это позволяет определить условие запроса для вывода дополнительной информации, и т. к. значение поля Key_tou является уникальным по определению, то и результат выборки будет включать одну необходимую запись.

В листинге 11.6 приведен полный код страницы AdminNoteTour.cfm.

Листинг 11.6. Код страницы AdminNoteTour.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm">

<link rel="STYLESHEET" type="text/css" href="main.css">

<script type="text/javascript" language="JavaScript"

src="main. js"></script> <script language="JavaScript">

if (ie) {document.write('<link rel="stylesheet" type="text/css"

href="main_ie.ess" title="master">');)

</script> </HEAD>

<BODY bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"

text="Black" alink="#107098" link="#OC1C47" vlink="#003366">

<CFIF isDefined("URL.key_tou")>

<CFQUERY NAME="GetTour" DATASOURCE="#application.dsn#"> SELECT Name_tou, Note_tou, Photo_tou

FROM Tour WHERE Key_tou = #Url.key_tou# </CFQUERY>

<CFOUTFUT QUERY="GetTour">

<p class="title">#Name_tou#</p>

<TABLE width="100%" border="0" cellspacing="2" cellpadding="0"> <TR> <TD>

<CFIF Photo_tou contains "gif">

<IMG src="#Photo_tou#" alt="" border="0"> </CFIF> </TD>

<TD class="txt">#Note_tou#</TD> </TR> </TABLE> </CPOUTPUT>

<CFELSE>

<script language="JavaScript">self.close();

</script> </CFIF> </BODY> </HTML>

Отметим, что в случае отсутствия переменной URL.key_tou страница AdminNoteTour.cfm автоматически закрывается.

Также вывести данные в ColdFusion можно с помощью тега <CFTABLE> в сочетании с тегом <CFCOL>. О чем, собственно говоря, и пойдет речь в следующем разделе с предварительным описанием тегов <CFTABLE> и <CFCOL>.

Тег <CFTABLE>

Синтаксис:

<CFTABLE QUERY = "query_name"

MAXROWS = "maxrows_table"

COLSPACING = "number_of_spaces"

HEADERLINES = "number_of_lines"

HTMLTABLE = "Yes | No"

BORDER = "Yes I No" COLHEADERS = "Yes | No"

STARTROW = "row_number"> </CFTABLE>

В табл. 11.5 представлено описание атрибутов тега <CFTABLE>.

Таблица 11.5. Описание атрибутов тега <CFTABLE>

Атрибут

Описание

QUERY

Имя запроса. Обязательный атрибут. Для вывода результатов запроса внутри блока <CFTABLE>

MAXROWS

Максимальное количество записей, которое следует выводить внутри блока <CFTABLE>. Необязательный атрибут

COLSPACING

Пространство между колонками. Необязательный атрибут. По умолчанию равен 2

HEADERLINES

Высота между заголовком и первым рядом. По умолчанию значение равно 2, что соответствует одному интервалу

HTMLTABLE

Формирование страницы в формате HTML 3.0. Необязательный атрибут. Возможные значения:

• Yes— да; • No — нет (по умолчанию)

BORDER

Рамка таблицы. Необязательный атрибут. Имеет смысл использовать при включении атрибута HTMLTABLE. Возможные значения:

• Yes — да; • No — нет (по умолчанию)

COLHEADERS


Отображение заголовка таблицы. Необязательный атрибут. Возможные значения: • Yes— да; • No — нет (по умолчанию)

STARTROW

Номер записи, с которой следует выводить полученные данные. Необязательный атрибут

 

Тег <CFCOL>

Синтаксис:

<CFCOL HEADER = "coluitin_header_text"

WIDTH = "number_indicating_width_of_colurrm" ALIGN = "Left | Right | Center" TEXT = "text">

В табл. 11.6 представлено описание атрибутов тега <CFCOL>.

Таблица 11.6. Описание атрибутов тега <CFCOL>

Атрибут

Описание

HEADER

Текст заголовка колонки. Обязательный атрибут

WIDTH

Ширина колонки в символах. Необязательный атрибут. По умолчанию значение равно 20

ALIGN

Выравнивание текста внутри колонки. Необязательный атрибут. Возможные значения:

• Left — по левому краю (по умолчанию);

• Right — по правому краю;

• Center — по центру

TEXT

Текст содержимого колонки. Текст может состоять из различных комбинаций и включать HTML-теги. Необязательный атрибут

 

Пример сочетания тегов <CFTABLE> и <CFCOL>

Мы не будем здесь приводить полный код страницы, покажем лишь, как можно было бы решить предыдущую задачу, где необходимо вывести все круизы, зарегистрированные в базе данных.

Напомним, что для решения данной задачи предварительно был построен запрос вот таким образом:

<CFQUERY NAME="GetTour" DATASOURCE="tapplication.dsn#">

SELECT Key_tou, Name_tou, PointDepart_tou,

NuraLandingPlaces_tou, Time_tou, CostAdult_tou,

CostChildren_tou, CostSenior_tou FROM Tour

</CFQUERY>

Далее выведем список полученных данных с использованием тегов

<CFTABLE> И <CFCOL>:

<CFTABLE QUERY="GetTour" COLHEADERS="Yes"

COLSPACING="0" HEADERLINES="1">

<CFCOL HEADER = "<b>Name tour</b>"

WIDTH = "27" ALIGN = "Left" TEXT = "

<a href='AdminUpdateTour.cfm?key_tou=

#Key_tou#'>tName_tou#</a>">

<CFCOL HEADER = "<b>Point of departure</b>"

WIDTH = "28" ALIGN = "Left"

TEXT = "#PointDepart_tout">

<CFCOL HEADER = "<b>Places</b>" WIDTH = "5"

ALIGN = "Right" TEXT = "#NumLandingPlaces tou#">

<CFCOL HEADER = "<b>Time</b>" WIDTH = "9" ALIGN = "Right"

TEXT = "#Time_tou#-hr">

<CFCOL HEADER = "

<b>Adults</b>" WIDTH = "9"

ALIGN = "Right"

TEXT = "$#CostAdult_tou#">

<CFCOL HEADER = "

<b>Children</b>" WIDTH = "9"

ALIGN = "Right"

TEXT = "$#CostChildren_tout">

<CFCOL HEADER = "

<b>Seniors</b>" WIDTH = "9"

ALIGN = "Right"

TEXT = "$#CostSenior_tou#">

<CFCOL HEADER = "

<b>Note</b>" WIDTH = "6"

ALIGN = "Center"

TEXT = "<a href='AdminNoteTour.

cfm?key_tou=iKey_tou#'

target= '_blank' XFONT face=' Wingdings'>

±</FONTx/a>"> </CFTABLE>

Модификация данных

Для модификации данных в ColdFusion можно воспользоваться несколькими вариантами: SQL-командой UPDATE внутри уже описанного нами тега <CFQUERY>, тегом <CFUPDATE>, а также тегом <CFGRID>, указываемого в рамках тега <CFFORM>. В данной главе будут рассмотрены только первые два способа.

Прежде чем привести пример по модификации данных, рассмотрим синтаксис SQL-команды UPDATE.

Команда UPDATE

Синтаксис:

UPDATE table_namelSET column_namel = expressionl

[, column_name2 = expression2 ...] WHERE filter_conditi'onl

[AND | OR filter_condition2 ...]]

Параметры:

Задает таблицу, в которой необходимо изменить записи.

Задает обновляемые столбцы и их новые значения. Если предложение WHERE опущено, каждая строка одного столбца обновляется одним и тем же значением.

Условие filter_condition задает критерий, которому должны удовлетворять изменяемые записи. Можно включить сколько угодно условий фильтрования, объединяя их операторами AND и OR. Можно также использовать оператор NOT, инвертирующий значение логического выражения.

Замечание

Команда UPDATE может модифицировать записи только в одной таблице.

 

Пример команды UPDATE

Предположим, нам необходимо организовать возможность модификации данных для уже зарегистрированных покупателей.

В этом случае требуется создать форму для редактирования данных с последующим изменением этих данных для конкретного покупателя. Тогда в нашем случае запрос в ColdFusion будет выглядеть следующим образом:

<CFQUERY NAME="UpdateTraveler" DATASOURCE="#application.dsn#">

UPDATE Traveler

SET EMail_tra = '#Form.EMail#',

FirstName_tra = 'IForm.FirstNamel',

LastName_tra = 'lForm.LastName#',

Middlelnitial_tra = '#Form.MiddleInitial#',

Password_tra = '#Form.Password!',

PhoneNum_tra = 'ttForm.PhoneNum#'

WHERE Key_tra = tSession.traveler.id# </CFQUERY>

Здесь в предложении SET перечислены обновляемые столбцы и их новые значения.

Следующим этапом обновляем переменную сессии session.traveler.name, поскольку значение этой переменной есть ни что иное, как сочетание значений двух модифицируемых полей, которые могли быть изменены. После чего открываем основную страницу и с помощью тега <CFEXIT> прекращаем выполнение последующего кода текущей страницы. Этот код таков:

<CFSET Session.traveler.name = #Form.FirstName#$" "&#Form.LastName#>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=BuyTickets.cfm"> <CFEXIT>

В листинге 11.7 представлен полный код страницы UpdateTra.cfm, позволяющей решить поставленную перед нами задачу.

Листинг 11.7. Код страницы UpdateTra.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm">

<link rel="STYLESHEET" type="text/css" href="main.css">

<script type="text/javascript" language="JavaScript"

src="main. js"></script> <style type="text/css">

<! --

#Update { position:absolute; left:20; top:140; width:200; height:100; margin:0;z-index:0;}

</style>

<script.language="JavaScript">

if (ie) (document.write('<link rel="stylesheet" type="text/css"

href="main_ie.css" title="master">');} </script> </HEAD>

<BODY onload="init(1)"

bgcolor="<CFOUTPUT>iapplication.BGColorPage#</CFOUTPUT>" text="Black" alink="#107098" link="#OC1C47" vlink="#003366">

<CFINCLUDE TEMPLATE = "BasicBlock.cfm">

<CFIF isDefined( "Session', traveler, id") >

<CFIF isDefined("Form.EMail")>

<CFSET Disuccessful = 1>

<CFSET msgError = "Warning Error!">

<CFIF Len(Form.EMail) le 5 and Form.EMail does not contain "@">

<CFSET msgError = msgError & "<br>" & #application.msgErrorl#>

<CFSET Disuccessful = 0> </CFIF> <CFIF Len(Form.Password) le 4>

<CFSET msgError - msgError & "<br>" & #application.msgError2#>

<CFSET Disuccessful = 0> </CFIF> <CFIF IsNumeric(Form.Password)>

<CFSET msgError = msgError & "<br>" & lapplication.msgError3#>

<CFSET Disuccessful = 0> </CFIF>

<CFIF Form.Password not equal Form.Confirm>

<CFSET msgError = msgError & "<br>" & tapplication.msgError4#>

<CFSET Disuccessful = 0> </CFIF> <CFIF Len(Form.FirstName) le 0>

<CFSET msgError = msgError & "<br>" & #application.msgError5#>

<CFSET Disuccessful = 0> </CFIF> <CFIF Len(Form.LastName) le 0>

<CFSET msgError = msgError & "<br>" & #application.msgError6#>

<CFSET Disuccessful = 0> </CFIF>

<CFIF YesNoFormat (Disuccessful) equal "No"> <!---Сшибки (Errors)--->

<CFSET email = #Form.EMail#> <CFSET fname = #Form.FirstName#>

<CFSET Iname = #Form.LastName#>

<CFSET middle = #Form.MiddleInitial#>

<CFSET phonen = #Form.PhoneNumtt> <CFELSE>

<!--- Обновление записи (Update record) --->

<CFQUERY NAME="UpdateTraveler" DATASOURCE="#application.dsn#">

UPDATE Traveler SET EMail_tra = '#Form.EMail#',

FirstName_tra = '#Form.FirstNarae#',

LastName_tra = '#Form.LastName#',

Middlelnitial_tra = '#Form.MiddleInitial#',

Password_tra = '#Form.Password#',

PhoneNum_tra = '#Form.PhoneNum#'

WHERE Key_tra = tSession.traveler.id# </CFQUERY>

<CFSET Session, traveler, name = #Form. FirstName# & " " &

#Form.LastName#>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=BuyTickets.cfm"> <CFEXIT> </CFIF> <CFELSE>

<CFQUERY NAME="GetTraveler" DATASOURCE="#application.dsn#"> SELECT *

FROM Traveler WHERE Key_tra = ISession.traveler.id# </CFQUERY>

<CFOUTPUT QUERY="GetTraveler"> <CFSET email = #EMail_tra#>

<CFSET fname = #FirstName_tra#> <CFSET Iname = lLastName_tra#>

<CFSET middle = #MiddleInitial_tra#> <CFSET phonen = #PhoneNum_tra#>

<CFSET msgError = ""> </CFOUTPUT> </CFIF> <DIV id="Update">

<FORM action='UpdateTra.cfm' method='post' name='forml'>

<TABLE border='0' cellspacing='0' cellpadding='0'> <TR>

<TR><TD colspan="2" height=l></TD>

<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>

<TD class="menleft"><a href="BuyTickets.cfm"

onMouseOver="mouse_over_bull('bul12',

'Update'}; window.status='Sign Up';

return true" onMouseOut="mouse_out_bull('bul12',

'Update'); window.status=''; return true">

<img name="bull2" src="bullet.gif" width="20"

height="20" border="0"></a></td>"

<TD width="55"><a href="BuyTickets.cfm"

onMouseOver="mouse_over_bull('bul12', 'Update');"

onMouseOut="mouse_out_bull('bul12', 'Update');"

class="menleft"> Log In</a></TD>

<TD bgcolor="#122c6d"></TD> <TD class="menleft">

<img name="bulll" src="bullet2.gif" width="20"

height="20" border="0"></TD>

<TD width="82" class="menleft">Update</TD>

<TR><td colspan="2" bgcolor="#122c6d" height=l></TD>

<TD colspan="2" height=l></TD></TR> </TR> </TABLE>

<table width="300" border="0" cellspacing="2" cellpadding="0">

<TR><TD colspan="2" align="center" class="txtError">

<CFOUTPUT>#msgError#</CFOUTPUT></TD></TR>

<TR><TD align="right" class="txtForm1">

E-Mail (Login)</td><td width="215" class="txtForm1">

<input name='EMail' size='16'

value="<CFOUTPUT>#email#</CFOUTPUT>">&nbsp;*</TD></TR>

<TR><TD align="right" class="txtForml"> Password</td>

<td class="txtForml"> <input type='password' name='Password'

size=' 16'>&nbsp; *</TD></TR>

<TR><TD align="right" class="txtForml">

Confirm</tdxtd class="txtForml">

<input type='password' name='Confirm'

size=' 16'>&nbsp;*</TD></TR>

<TR><TD align="right" class="txtForml"> First Name</tdxtd class="txtForml"> <input name='FirstName' size='16'

value="<CFOUTPUT>#fname#</CFOUTPUT>">&nbsp;* </TD></TR>

<TRXTD align="right" class="txtForml"> Last Name</td>

<td class="txtForml"> <input name='LastName' size='16'

value="<CFOUTPUT>#lname#</CFOUTPUT>">&nbsp;*</TD></TR>

<TRXTD align="right" class="txtForml"> Middle Initial</td>

<td> <input name='MiddleInitial' size='l'

value="<CFOUTPUT>#middle#</CFOUTPUT>"></TD></TR>

<TR><TD align="right" class="txtForml"> Phone Num.</td>

<td> <input name='PhoneNura' size='10'

value="<CFOUTPUT>#phonen#</CFOUTPUT>"></TD></TR>

<TR><td align="right">

<input type='submit' value=' Set '></TD><TD> <input type='reset' value='Reset'></TD></TR>

</TABLE> </FORM> </DIV>

<CFELSE>

<META HTTP-EQUIV="Refresh" CONTENT="0;UR]>BuyTickets.cfm"> </CFIF>

</BODY> </HTML>

Отметим, что сообщения об ошибках определены в конфигурационном файле Application. cfm так, как это показано в разд. "Пример файла Application. cfm" гл. 10.

Также для модификации данных в ColdFusion можно использовать тег <CFUPDATE>, о чем и пойдет речь в следующем разделе с предварительным описанием этого тега.

Тег <CFUPDATE>

Синтаксис:

<CFUPDATE DATASOURCE = "ds_name" DBTYPE = "type" OBSERVER = "dbms"

DBNAME = "database name"

TABLENAME = "tbl_name"

CONNECTSTRING = "connection string"

TABLEOWNER = "owner"

TABLEQUALIFIER = "tbl_qualifier"

USERNAME = "username"

PASSWORD = "password"

PROVIDER = "COMProvider"

PROVIDERDSN = "datasource"

FORMFIELD3 = "formfieldl, formfield2, ...">

Атрибуты тега <CFUPDATE> полностью идентичны с атрибутами уже описанного тега <CFINSERT> (см. табл. 11.3).

Пример тега <CFUPDATE>

Чтобы продемонстрировать использование тега <CFUPDATE>, предназначенного для модификации данных, рассмотрим пример, позволяющий изменять информацию об уже зарегистрированных экскурсиях и круизах.

Для решения данной задачи необходимо создать форму, предназначенную для редактирования необходимых данных с целью их последующего изменения по выбранному круизу. Тогда для нашего примера код модификации данных будет выглядеть следующим образом:

<CFUPDATE DATASOURCE = "#application.dsn#"

TABLENAME = "Tour" FORMFIELDS = "Key_tou,Name_tou,PointDepart_tou,

NumLandingPlaces_tou,Time_tou,CostAdult_tou,

CostChildren_tou,CostSenior_tou,Photo_tou,Note_tou">

В листинге 11.8 приведен полный код страницы AdmmUpdateTour.cfm, позволяющей решить описанную выше задачу.

Листинг 11.8. Код страницы AdminUpdateTour.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm">

<link rel="STYLESHEET" type="text/css" href="main.ess">

<script type="text/javascript" language="JavaScript"

src="main. js"></script> <sty'le type="text/ess"> <! --

#Tour { position:absolute; left:20; top:140; width:200; height:100; margin:0; z-index:0;}

</style>

<script language="JavaScript">

if (ie) {document.write('<link rel="stylesheet" type="text/css"

href="main_ie.css" title="master">'};} </script> </HEAD> <BODY onload="init(1)"

bgcolor="<CFOUTPUT>#application.BGColorPage#

</CFOUTPUT>" text="Black" alink="#107098" link="#OC1C47" vlink="#003366">

<CFINCLUDE TEMPLATE = "BasicBlock.cfm">

<CFIF isDefined("key_tou")>

<CFIF isDefined("Form.Name_tou")> <CFSET Disuccessful = 1>

<CFSET msgError = "Warning Error!">

<CFIF Len(Form.Name_tou) le 0 or Len(Form.PointDepart_tou) le 0 or Len(Form.NumLandingPlaces_tou) le 0 or Len(Form.Time_tou) le 0 or Len(Form.CostAdult_tou) le 0 or Len(Form.CostChildren_tou) le 0 or Len(Form.CostSenior_tou) le 0> <CFSET msgError = msgError & "<br>" & "The fields marked with

a symbol *, should not be empty!">

<CFSET Disuccessful = 0> </CFIF>

<CFIF YesNoFormat(Disuccessful) equal "No"> <!--- Errors --->

<CFSET Name_tou = IForm.Name_tou#>

<CFSET PointDepart_tou = #Form.PointDepart_tou#>

<CFSET NumLandingPlaces_tou = #Form.NumLandingPlaces_tou#>

<CFSET Time_tou = #Form.Time_tou#>

<CFSET CostAdult_tou = #Form.CostAdult_tou#>

<CFSET CostChildren_tou = #Form.CostChildren_toutt>

<CFSET CostSenior_tou = #Form.CostSenior_tou#>

<CFSET Photo_tou = #Form.Photo_toui>

<CFSET Note_tou = #Form.Note_tou#> <CFELSE>

<!--- Обновление записи (Update record) --->

<CFUPDATE DATASOURCE = "#application.dsn#" TABLENAME = "Tour" FORMFIELDS = "Name_tou,PointDepart_tou,

NumLandingPlaces_tou,

Time_tou,CostAdult_tou,CostChildren_tou,

CostSenior_tou,Photo_tou,Note_tou">

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=AdminListTour.cfm">

<CFEXIT> </CFIF> <CFELSE>

<CFSET msgError = "">

<CFQUERY NAME="GetTour" DATASOURCE="tapplication.dsn#">

SELECT *

FROM Tour WHERE Key_tou = '#key_tou#' </CFQUERY>

<CFOUTPUT QUERY="GetTour">

<CFSET Name_tou = #Name_tou#>

<CFSET PointDepart_tou = #PointDepart_tou#>

<CFSET NumLandingPlaces_tou = #NumLandingPlaces_tou#>

<CFSET Tirae_tou = #Time_tou#>

<CFSET CostAdult_tou = #CostAdult_tou#>

<CFSET CostChildren_tou = #CostChildren_tou#>

<CFSET CostSenior_tou = #CostSenior_tou#>

<CFSET Photo_tou = #Photo_tou#>

<CFSET Note_tou = #Note_tou#> </CFOUTPUT> </CFIF>

<DIV id="Tour">

<FORM action='AdminUpdateTour.cfm' method='post' name='form1'>

<TABLE width="370" border="0" cellspacing="0" cellpadding="0"> <TR>

<TR><TD colspan="2" height=l></TD>

<TD colspan="4" bgcolor="#122c6d" height=l></TD></TR>

<TD class="menleft"><a href="AdminListTour.cfm"

onMouseOver="mouse_over_bull('bull2', 'Tour');

window.status='List Tour'; return true"

onMouseOut="mouse_out_bull('bull2', 'Tour');

window.status=''; return true">

<IMG name="bull2" src="bullet.gif" width="20" height="20"

border="0"></a></TD>

<TD width="155">

<a href="AdminListTour.cfm"

onMouseOver="mouse over bull('bull2', 'Tour');"

onMouseOut="mouse_out_bull('bull2', 'Tour');

"class="menleft"> List Tour</a></TD>

<TD bgcolor="#122c6d"></TD>

<TD class="menleft">

<IMG name="bulll" src="bullet2.gif" width="20" height="20"

border="0"></td>

<TD width="215" class="menleft">

Update Tour&nbsp;(<a

href="javascript:del('AdminDeleteTour

.cfm?key_tou=<CFOUTPUT>#key_tou# </CFOUTPUT>')

;" class="menleft_u">Delete Tour</a>)

</TD>

<TR><td colspan="2" bgcolor="#122c6d" height<=l></TD>

<TD colspan="2" height=l></TD></TR> </TR> </TABLE>

<TABLE widtb="390" border="0" cellspacing="2" cellpadding="0">

<TR><td colspan="2" align="center" class="txtError">

<CFOUTPUT>#msgError#</CFOUTPUT></TD></TR>

<TR><td align="right" class="txtForm1">

Name tour.</td><td width="230" class="txtForml">

<input name='Name_tou' size='30'

value="<CFOUTPUT>#Name_tou#</CFOUTPUT>">Snbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">

Point of departure</tdxtd class="txtForml">

<input name='PointDepart_tou' size='30'

value="<CFOUTPUT>#PointDepart_toul

</CFOUTPUT>">&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">

Number of landing places</td>

<td class="txtForml">

<input name='NumLandingPlaces_tou' size='6'

value="<CFOUTPUT>#NumLandingPlaces_toul

</CFOUTPUT>">&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">

Time in tour</td><td class="txtForml">

<input name='Time_tou' size='2'

value="<CFOUTPUT>#Time_tou#

</CFOUTPUT>">&nbsp;hours,Snbsp;* </TD></TR>

<TR><TD align=" right" class="txtForml">

Cost for adults</tdxtd class="txtForml">

<input name='CostAdult__tou' size='6'

value="<CFOUTPUT>#CostAdult_tou#

</CFOUTPUT>">&nbsp; $, &nbsp; * </TD></TR>

<TR><TD align="right" class="txtForm1">

Cost for children</tdxtd class="txtForml">

<input name='CostChildren_tou' size='6'

value="<CFOaTPUT>#CostChildren_tou#

</CFOUTPUT>">&nbsp;$,&nbsp;* </TD></TR>

<TR><TD align="right" class="txtForml">

Cost for senior citizens</tdxtd class="txtForml">

<input name='CostSenior_tou' size='6'

value="<CFOUTPUT>#CostSenior_tou#

</CFOUTPUT>">&nbsp; $, &nbsp; * </TD></TR>

<TR><TD align="right" class="txtForml">

Photo</TD><TD> <input name= ' Photo__tou ' size='23'

value="<CFOUTPUT>iPhoto_tou#</CFOUTPUT>"></TD></TR>

<TR><TD align="right" class="txtForml">

Note</TD><TD> <textarea name = "Note_tou" cols = "33"

rows = "4"><CFOUTPUT>#Note tou#</CFOUTPUT>

</textarea>

</TD></TR>

<TR><TD><input type="Hidden" nanie="key_tou"

value="<CFOUTPUT>#key_tou#</CFOUTPUT>"></td><td>

<TR><TD align="right">

<input type=' submit' value=' Set '></TD><TD>

<input type=' reset' value= ' Reset '></TD></TR>

</TABLE> </FORM>

</DIV>

<CFELSE>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=AdminListTour.cfm"> </CFIF> </BODY> </HTML>

Обращаем ваше внимание, что на страницу AdminUpdateTour.cfm пользователь попадает со страницы AdminListTour.cfm, откуда и передается переменная key_tou, с помощью которой производится выборка необходимых данных.

В рассмотренном примере встречается ссылка на страницу AdminDeleteTour.cfm, предназначенную для удаления текущей записи, о чем, собственно говоря, и пойдет речь далее.

Удаление данных

Для удаления данных в ColdFusion существует опять же несколько способов: применение SQL-команды DELETE внутри уже описанного нами тега <CFQUERY>, указание тега <CFGRID>, используемого в рамках тега <CFFORM>. Впрочем, тег <CFGRID> позволяет только визуализировать процесс удаления данных, а для непосредственного удаления, так или иначе, необходимо использовать команду DELETE. В данной главе будет рассмотрен только первый способ.

Команда DELETE

Синтаксис:

DZLETE FROM table_name

[WHERE filter_conditionl [AND | OR filter_condition2 ...]]

Параметры:

Задает таблицу, в которой предполагается удаление записей.

Указывает на удаление только определенных записей.

Условие fiiter_condition устанавливает критерий, которому должны удовлетворять записи, предназначенные для удаления. Можно задать сколько угодно условий фильтрования, объединяя их с помощью операторов AND и OR. Можно также пользоваться оператором NOT, инвертирующим значение логического выражения.

Пример команды DELETE

Предположим, нам необходимо в режиме обновления данных по тому или иному круизу предоставить возможность удалить текущую запись.

В этом случае требуется лишь установить ссылку на страницу, отвечающую за удаление данных с обязательным включением в URL-адрес значения уникального ключа для удаления только текущей записи. К примеру, так:

<а href="AdminDeleteTour.cfm?key_tou= <CFOUTPUT>#key_tou#

</CFOUTPUT>') ">Delete Tour</a>

А уже непосредственно запрос на удаление в указанной странице может выглядеть следующим образом:

<CFQUERY NAME="DeleteTour" DATASOURCE="#application.dsn#">

DELETE Tour WHERE Key_tou = '#key_tou#' </CFQUERY>

Однако правильно было бы перед удалением записи обращаться к пользователю за подтверждением удаления, и здесь могут быть разные решения.

Для реализации подтверждения на удаление мы несколько преобразуем ссылку:

<а href="javascript:del('AdminDeleteTour.cfm?key_tou=

<CFOUTPUT>#key_tou#</CFOUTPUT>');"

class="menleft_u">Delete Tour</a>

где del — заранее созданная функция и помещенная в основной файл JavaScript main.js. Приведем код этой функции:

function del(url) { if(ie){

_del = self.showModalDialog ("DialogQuestion.cfm?text_=You really

want to delete the current record?", null,

"status.:no; center: yes;help:no;

minimize:no;maximize:no;border:thin;

statusbar:no;dialogWidth:305px;

dialogHeight:110px"); if(_del==true) {

location.href=url; } } else {

location.href=url; } }

Необходимо отметить, что с помощью данной функции мы открываем модальное окно только для браузера MS Internet Explorer. Для остальных же браузеров запись удаляется без подтверждения. Впрочем, у вас есть возможность исправить данный недочет и самостоятельно решить эту задачу. Мы же приведем пример страницы DialogQuestion.cfm, исполняющей роль диалога подтверждения удаления записи.

Листинг 11.9. Код страницы DialogQuestion.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD. cfm">

<link rel="STYLESHEET" type=" text /ess" href="main.css">

<style type="text/css">

<! —

fpic_ {position: absolute; left: 10; top: 10; margin: 0;} — >

</style> </HEAD> <BODY bgcolor="#COCOCO">

<div id="pic_">

<img src="question_icon.gif ">

<br>

<p class="dialog_">

&nbsp; snbsp; &nbsp; Snbsp; &nbsp; &nbsp; &nbsp; &nbsp;

Snbsp; Snbsp; &nbsp; &nbsp; Snbsp; &nbsp; &nbsp; <CFIF isDefined("URL.text_")>

<CFOUTPUT>#URL . text_#</CFOUTPUT> </CFIF>

</р>

<р ALIGN="ccnter"> &nbsp;snbsp;

<BUTTON ID="btnDelYes" style="height: 23; ">

<SPAN class="dialog">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Yes&nbsp;Snbsp;&nbsp;&nbsp;&nbsp;&nbsp;</BUTTON>

&nbsp;&nbsp;finbsp;&nbsp;Snbsp;

<BUTTON ID="btnDelNo" style="height:23;">

<SPAN class="dialog">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; No&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </BUTTON> </p>

<SCRIPT LANGUAGE="VBScript"> <! —

Sub btnDelYesJDnClick self. returnValue=true self

. close

End Sub

Sub btnDelNo_OnClick self. returnValue=false self

. close

End Sub — >

</SCRIPT> </BODY> </HTML>

В заключение описания удаления данных посредством ColdFusion приведем пример страницы AdminDeleteTour.cfm, где, в общем-то, и совершается "обряд" удаления выбранного круиза.

Листинг 11.10. Код страницы AdminDeleteTour.cfm

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD. cfm"> </HEAD>

<BODY bgcolo"r="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"

text="Black" alink="#107098" link="#OC1C47" vlink="#003366"> <CFIF isDefined("key_tou")>

<CFQOERY NAME="DeleteTour" DATASOURCE="#application.dsn#">

DELETE Tour WHERE Key_tou = '#key_tou#' </CFQUERY> </CFIF>

<META HTTP-EQUIV="Ref resh" CONTENT="0;URL=AdminListTour . cfm">

</BODY> </HTML>

Отметим лишь, что по мере удаления записей пользователь возвращается к списку еще пока существующих круизов.

Транзакции

Транзакция — это логическая единица работы, т. е. транзакция в приложении обеспечивает защиту путем выделения секции программного кода в качестве единицы восстановления.

Рассмотрим пример. Предположим, что таблица TOUR включает дополнительный атрибут TotaiTraveier, представляющий собой общее число путешественников для каждого круиза. Значение TotaiTraveier для любого круиза должно быть равным сумме купленных билетов. Покупка же билетов регистрируется в таблице TICKET. Данный пример предполагает, что речь идет о выполнении двух операций: добавлении новой записи в таблицу TICKET и модификации значения поля TotaiTraveier в таблице TOUR для выбранного круиза. При этом в базе данных между двумя указанными операциями временно, нарушается требование, что значение TotaiTraveier для круиза равно сумме купленных билетов на конкретный круиз. Таким образом, логическая единица работы — не просто одиночная операция системы баз данных, а скорее согласование нескольких таких операций. И не допустимо, чтобы одна из операций была выполнена, а другая нет, поскольку база данных остается в несогласованном состоянии. В идеальном случае должны быть выполнены обе операции. Однако нельзя обеспечить абсолютную гарантию, что так и случится. Не исключена вероятность, что система может дать сбой между двумя операциями, или же на второй операции произойдет арифметическое переполнение и т. д. Система же, поддерживающая процесс транзакции, гарантирует, что если во время выполнения неких операций произошла ошибка, то все результаты операций будут аннулированы. Таким образом, транзакция или выполняется целиком, или полностью отменяется.

Для установки транзакции в ColdFusion необходимо использовать тег <CFTRANSACTION>.

Тег <CFTRANSACTION>

Синтаксис:

<CFTRANSACTION ACTION = "Begin | Commit I Rollback"

ISOLATION = "Read_Uncommitted | Read_Committed |

Repeatable_Read I Serializable"> </CFTRANSACTION>

В табл. 11.7 представлено описание атрибутов тега <CFTRANSACTION>.

Таблица 11.7. Описание атрибутов тега <CFTRANSACTION>

Атрибут

Описание

ACTION

Действие. Необязательный атрибут. Возможные значения: • Begin — начать транзакцию (по умолчанию);

• Commit — применить изменения, совершенные с момента начала транзакции;

• Rollback — отменить все изменения, сделанные с момента начала транзакции

ISOLATION

Уровень изоляции. Необязательный атрибут. Возможные значения:

• Read Uncommitted— незавершенное считывание, предназначено для "неаккуратных" считываний;

• Read Committed — завершенное считывание; • Repeatable Read — повторяемое считывание;

• Serializable — способность к упорядочению, по сути, является единственным безопасным уровнем

В пределах блока транзакции можно применять изменения, совершенные с момента начала транзакции, указав

<CFTRANSACTION ACTION = "commit"/>

либо отменить все изменения, добавив

<CFTRANSACTION ACTION = "rollback"/>

Пример тега <CFTRANSACTION>

Усложним задачу удаления круизов. В следующем примере (листинг 11.11) с использованием транзакции удаляется запись со сведениями о выбранном круизе и все связанные записи с данными о расписании и забронированных билетах.

Листинг 11.11. Код страницы AdminDeleteTour.cfm с добавлением блока транзакции

<HTML> <HEAD>

<CFINCLUDE TEMPLATE = "MyHEAD.cfm"> </HEAD>

<BODY bgcolor="<CFOUTPUT>#application.BGColorPage#</CFOUTPUT>"

text="Black" alink="#107098" link="#0C1C47" vlink="#003366">

<CFIF isDefined("key_tou")>

<CETRANSACTION ACTION="Begin">

<CFQUERY NAME="DeleteTicket" DATASOURCE="#application.dsn#">

DELETE Ticket

WHERE Key_tou = '#key_tou#' </CFQUERY>

<CFQUERY NAME="DeleteSchedule" DATASOURCE="#application.dsn#">

DELETE Schedule_

WHERE Key_tou = '#key_tou#' </CFQUERY>

<CFQUERY NAME="DeleteTour" DATASOURCE="fapplication.dsn#">

DELETE Tour

WHERE Key_tou = '#key_tou#' </CFQUERY>

<CFTRANSACTION ACTION="Commit"/> </CFTRANSACTION> </CFIF>

<META HTTP-EQUIV="Refresh" CONTENT="0;URL=AdminListTour.cfm">

</BODY> </HTML>

Если при выполнении одной из команд DELETE возникает ошибка, транзакция выполнит откат, что позволит избежать конфликтов.

Резюме

В заключение следует отметить, что SQL-запросы являются одним из главных инструментов работы с данными, и если вам пока трудно дается написание SQL-запросов вручную, вы можете прибегнуть к помощи конструктора запросов ColdFusion Studio, подробно описанного в разд. "Базы данных" гл. 4. Подведем итог. В данной главе мы познакомились и использовали CFML-теги:

<CFQUERY>, <CFINSERT>, <CFTABE>, <CFCOL>, <CFUPDATE>, <CFTRANSACTION>.